﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AStartCom {

    static AStartCom m_Instance;

    private AStartCom()
    {

    
    }

    public static AStartCom getInstance(){

        if(m_Instance == null){

            m_Instance = new AStartCom();

        }

        return m_Instance;

    }

    public Point[] GetResultPath(int[,] mapGrid, Vector3 startPos,Vector3 endPos, List<GameObject> cubeList)
    {

        List<Point> MapPointInfo = new List<Point>();

        Point startPoint = null;

        Point endPoint = null;

        for (int i = 0; i < mapGrid.GetLength(0); i++)
        {

            for (int j = 0; j < mapGrid.GetLength(1); j++)
            {

                int xPos = i;

                int zPos = j;

                Point po = new Point(xPos, zPos, null, endPos);

                MapPointInfo.Add(po);

                if (xPos == startPos.x && zPos == startPos.z)
                {

                    startPoint = po;

                }
                else if (xPos == endPos.x && zPos == endPos.z)
                {

                    endPoint = po;

                }

            }

        }

        List<Point> OpenPointList = new List<Point>();

        List<Point> ClosePointList = new List<Point>();

        //起始点赋值
        OpenPointList.Add(startPoint);

        SetGHValueUI(cubeList[startPoint.x * 10 + startPoint.z], startPoint.G, startPoint.H, startPoint.F, startPoint.x * 10 + startPoint.z, startPoint.x, startPoint.z);

        while (OpenPointList.Count > 0)
        {

            Point currentPoint = FindMinOfPoint(OpenPointList);

            OpenPointList.Remove(currentPoint);

            ClosePointList.Add(currentPoint);

            //获取当前点的周围点
            List<Point> roundPoint = GetPointRound(currentPoint, mapGrid, endPos, MapPointInfo);

            for (int i = roundPoint.Count - 1; i >= 0; i--)
            {

                for(int j = ClosePointList.Count -1; j >= 0; j--)
                {

                    if (roundPoint[i].IsEquals(ClosePointList[j]))
                    {

                        roundPoint.Remove(roundPoint[i]);

                        break;

                    }

                }

            }

            foreach (Point temp in roundPoint)
            {

                if (OpenPointList.IndexOf(temp)> -1)
                {

                    float nowG = Point.CalculateGValue(temp, temp.ParentPoint);

                    if (nowG < temp.G)
                    {

                        temp.UpdateParent(currentPoint, nowG);

                        GameObject obj = cubeList[temp.x * 10 + temp.z];

                        SetGHValueUI(obj, temp.G, temp.H,temp.F, temp.x * 10 + temp.z, temp.x, temp.z);

                    }

                }
                else
                {

                    temp.ParentPoint = currentPoint;

                    Point.CalculateF(temp, endPoint);
                    
                    GameObject obj = cubeList[temp.x * 10 + temp.z];

                    SetGHValueUI(obj, temp.G, temp.H,temp.F, temp.x * 10 + temp.z, temp.x, temp.z);

                    OpenPointList.Add(temp);

                }

            }

            if (currentPoint.IsEquals(endPoint))
            {

                break;

            }

        }

        //获取路径点
        List<Point> paths = new List<Point>();

        Point p = endPoint;

        paths.Add(endPoint);

        while (true)
        {

            paths.Add(p.ParentPoint);

            p = p.ParentPoint;

            if (p.ParentPoint == startPoint || p.ParentPoint == null)
            {

                break;

            }

        }

        paths.Reverse();

        return paths.ToArray();

    }
    
    void SetGHValueUI(GameObject obj, float G, float H,float F, float index,float x,float z)
    {

        Text[] ValueText = obj.GetComponentsInChildren<Text>();

        for (int i = 0; i < ValueText.Length; i++)
        {

            if (ValueText[i].name == "GValueText")
            {

                ValueText[i].text = G.ToString();

            }
            else if (ValueText[i].name == "HValueText")
            {

                ValueText[i].text = H.ToString();

            }
            else if (ValueText[i].name == "FValueText")
            {

                ValueText[i].text = F.ToString();

            }
            else if (ValueText[i].name == "IndexValueText")
            {

                ValueText[i].text = index.ToString();

            }
            else if (ValueText[i].name == "XValueText")
            {

                ValueText[i].text = x.ToString();

            }
            else if (ValueText[i].name == "ZValueText")
            {

                ValueText[i].text = z.ToString();

            }

        }

    }

    Point FindMinOfPoint(List<Point> openList)
    {

        float f = openList[0].F;

        Point minPoint = openList[0];

        for (int i = 1; i < openList.Count; i++)
        {

            if (openList[i].F < f)
            {

                minPoint = openList[i];

                f = minPoint.F;

            }

        }

        return minPoint;

    }

    int GetItemIndexAtList(List<Point> ps, Point p)
    {

        for (int i = 0; i < ps.Count; i++)
        {

            if (ps[i].IsEquals(p))
            {

                return i;

            }

        }

        return -1;

    }

    Point GetPointWithIndex(int x, int z, List<Point> MapPointInfo, int[,] mapGrid)
    {

        if (x < 0 || z < 0)
        {

            return null;

        }
        else if (x < 0 || x >= mapGrid.GetLength(0))
        {

            return null;

        }
        else if (z < 0 || z >= mapGrid.GetLength(1))
        {

            return null;

        }
        //非障碍
        else if (mapGrid[x, z] == 1)
        {

            return null;

        }

        return MapPointInfo[x * 10 + z];

    }

    public List<Point> GetPointRound(Point po, int[,] mapGrid, Vector3 endPoint, List<Point> MapPointInfo)
    {

        List<Point> roundPoint = new List<Point>();

        int x = po.x;

        int z = po.z;

        for (int i = -1; i <= 1; i++)
        {

            for (int j = -1; j <= 1; j++)
            {

                if (i == 0 && j == 0)
                {

                    continue;

                }

                Point temp = GetPointWithIndex(i + x, j + z, MapPointInfo, mapGrid);

                if (temp != null)
                {

                    roundPoint.Add(temp);

                }

            }

        }

        return roundPoint;

    }

    public Point GetMinFValue(List<Point> PointList)
    {

        Point minFPoint = null;

        for (int i = 0; i < PointList.Count; i++)
        {

            if (minFPoint == null)
            {

                minFPoint = PointList[i];

            }
            else
            {

                if (minFPoint.F > PointList[i].F)
                {

                    minFPoint = PointList[i];

                }

            }

        }

        return minFPoint;
    }


    public int[] GetAreaIndex(int index,int mapWidth,int mapLen)
    {

        List<int> areaList = new List<int>();

        return areaList.ToArray();

    }

}
